{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "source": [
    "\n",
    "\n",
    "<!-- TEASER_END -->\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": [
    "import functools"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "8 9\n",
      "290 9\n",
      "308 9\n",
      "320 9\n",
      "8 9\n",
      "218 9\n",
      "320 9\n",
      "279 9\n",
      "289 9\n",
      "320 9\n",
      "9991 9\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "CacheInfo(hits=3, misses=8, maxsize=32, currsize=8)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "import urllib\n",
    "\n",
    "@functools.lru_cache(maxsize=32)\n",
    "def get_pep(num):\n",
    "    'Retrieve text of a Python Enhancement Proposal'\n",
    "    resource = 'http://www.python.org/dev/peps/pep-%04d/' % num\n",
    "    try:\n",
    "        \n",
    "        with urllib.request.urlopen(resource) as s:\n",
    "            return s.read()\n",
    "    except:\n",
    "        return 'Not Found'\n",
    "\n",
    "\n",
    "for n in 8, 290, 308, 320, 8, 218, 320, 279, 289, 320, 9991:\n",
    "    pep = get_pep(n)\n",
    "    print(n, len(pep))\n",
    "\n",
    "\n",
    "get_pep.cache_info()\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "18"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# functools.partial固定函数可选参数，返回一个函数对象\n",
    "basetwo = functools.partial(int, base=2)\n",
    "basetwo.__doc__ = 'Convert base 2 string to an int.'\n",
    "\n",
    "assert(basetwo('10010') == int('10010', base=2))\n",
    "basetwo('10010')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "True"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "# functools.partialmethod 固定对象成员函数\n",
    "class Cell(object):\n",
    "    def __init__(self):\n",
    "        self._alive = False\n",
    "\n",
    "    @property\n",
    "    def alive(self):\n",
    "        return self._alive\n",
    "\n",
    "    def set_state(self, state):\n",
    "        self._alive = bool(state)\n",
    "\n",
    "    set_alive = functools.partialmethod(set_state, True)\n",
    "    set_dead = functools.partialmethod(set_state, False)\n",
    "\n",
    "\n",
    "c = Cell()\n",
    "c.alive\n",
    "\n",
    "c.set_alive()\n",
    "c.alive\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "\n",
    "functools.reduce(lambda x, y: x+[y], range(10), [])"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "print A obj:  <__main__.A object at 0x10c944978>\n",
      "print B obj:  <__main__.B object at 0x10c9449e8>\n",
      "print C obj:  <__main__.C object at 0x10c944978>\n",
      "print B obj:  <__main__.D object at 0x10c9449e8>\n"
     ]
    }
   ],
   "source": [
    "# 函数分发封装\n",
    "\n",
    "@functools.singledispatch\n",
    "def fun(arg, verbose=False):\n",
    "    if verbose:\n",
    "        print(\"Let me just say,\", end=\" \")\n",
    "\n",
    "    print(arg)\n",
    "\n",
    "\n",
    "class A(object):\n",
    "    name = \"A\"\n",
    "\n",
    "\n",
    "class B(A):\n",
    "    name = \"B\"\n",
    "\n",
    "\n",
    "class C(B):\n",
    "    name = \"C\"\n",
    "\n",
    "\n",
    "class D(B):\n",
    "    name = \"C\"\n",
    "\n",
    "\n",
    "@fun.register(A)\n",
    "def _(obj):\n",
    "    print(\"print A obj: \", obj)\n",
    "\n",
    "\n",
    "@fun.register(B)\n",
    "def _(obj):\n",
    "    print(\"print B obj: \", obj)\n",
    "\n",
    "\n",
    "@fun.register(C)\n",
    "def _(obj):\n",
    "    print(\"print C obj: \", obj)\n",
    "\n",
    "\n",
    "\n",
    "fun(A())\n",
    "\n",
    "fun(B())\n",
    "\n",
    "fun(C())\n",
    "\n",
    "fun(D())\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Calling decorated function\n",
      "Called example function\n",
      "['__annotations__', '__call__', '__class__', '__closure__', '__code__', '__defaults__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__get__', '__getattribute__', '__globals__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__kwdefaults__', '__le__', '__lt__', '__module__', '__name__', '__ne__', '__new__', '__qualname__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__wrapped__']\n",
      "functools.partial(<function update_wrapper at 0x10aa9d8c8>, wrapped=<class 'int'>, assigned=('__module__', '__name__', '__qualname__', '__doc__', '__annotations__'), updated=('__dict__',))\n"
     ]
    }
   ],
   "source": [
    "# functools.wraps 函数包装(等同partial(update_wrapper, wrapped=wrapped, assigned=assigned, updated=updated))\n",
    "\n",
    "def my_decorator(f):\n",
    "    @functools.wraps(f)\n",
    "    def wrapper(*args, **kwds):\n",
    "        print('Calling decorated function')\n",
    "        return f(*args, **kwds)\n",
    "    return wrapper\n",
    "\n",
    "@my_decorator\n",
    "def example():\n",
    "    \"\"\"Docstring\"\"\"\n",
    "    print('Called example function')\n",
    "\n",
    "\n",
    "example()\n",
    "\n",
    "print(dir(example))\n",
    "\n",
    "print(functools.wraps(int))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "autoscroll": false,
    "collapsed": false,
    "ein.hycell": false,
    "ein.tags": "worksheet-0",
    "slideshow": {
     "slide_type": "-"
    }
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "name": "python3"
  },
  "name": "python-function-tools.ipynb",
  "nikola": {
   "category": "",
   "date": "2019-04-02 16:55:28 UTC+08:00",
   "description": "",
   "link": "",
   "slug": "python-function-tools",
   "tags": "",
   "title": "python function tools",
   "type": "text"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
